<?php
declare(strict_types=1);
namespace Service\VenderClient\PayCenterApi;
use Service\Code\Normal;
use Service\BaseService;
use Service\ExtraService\TaskWorker;

class HnapayApiClient extends BaseService
{
    protected $config;
    protected $url = 'https://uwebgate.hnapay.com/webgate/unifiedAPI.htm';
    public function __construct( array $apiBody = [] )
    {
        $this->config = $apiBody;
    }
    
    /**
     * 发起支付
     * @param array $body
     */
    public function payOrder( array $body = [])
    {
        $head=[
            'serCode'   => '101005',//服务代码
            'merCode'   => $this->config['merCode'],//商户代码
            'orderId'   => (string)time().rand(100,999),//请求流水号交易唯一标识
            'merDate'   => date('Ymd'),//商户订单日期
            'merTime'   => date('His'),//商户订单时间
            'versionNo' => '2.0',
            'signType'  => '2'
        ];
        $content = [
            //商户交易订单号
            'merOrderId'        => $body['merOrderId'],
            //商户显示名称
            'displayName'       => $body['displayName'],
            //商品名称
            'goodsName'         => $body['goodsName'],
            //商品数量
            'goodsCount'        => (int)$body['goodsCount'],
            //商品类别
            'goodsType'         => $body['goodsType']??'',//tradeType=0004 货物贸易时必填服装-00 食品-01 电子产 品-02 箱包-03 日用品-04 保健品-05 化妆品-06 家电 -07tradeType=0013 旅游服务时必 填旅游签证-22
            //订单金额
            'orderAmount'       => (int)(round($body['orderAmount']*100,2)),//订单金额。以分为单位。
            'orderCurrencyCode' => 'CNY',//订单币种
            //贸易类型
            'tradeType'         => $body['tradeType']??'0002',//0001-担保交易，0002-即时付 款，0003-跨境支付，0004-货物 贸易，0005-酒店住宿，0006-机 票旅游，0007-留学教育，0008- 国际会展，0009-国际会议， 0010-物流支付，0013-旅游服 务，0014-软件服务，0015-管理咨询，0016-设计咨询 注:境内订单上送 0002，如果是跨 境进口订单，需上送 0004-0016 对 应的贸易类型，否则订单无法用于 后续购付汇。Eg:进口商品上送 0004。
            //支付方式
            'payType'           => (string)$body['payType'],//填写数字代码。1:B2C (B2C 直连到银行) 2:B2B(B2B 直连到银行)3:QUICK_PAY(快捷支付，该接口 为预支付申请) 4:QRCODE(扫码支付，商户被扫) 5:JS (公众号，小程序/服务 窗支付) 6:PAYCODE(刷卡支付，商户主 扫)7:APP(APP 支付) 8:H5 直连 9:预付费卡支付
            //目标机构资金代码
            'orgCode'           => $body['orgCode'],//填写机构英文代码,大写。参见 9.3 机构代码payType=1、2 或 3 时必填，支 持:CMB,ICBC...(具体参见银行 机构代码);payType=4 时必填，支持: ALIPAY(支付宝),WECHATPAY(微 信)，UNIONPAY(银联)，QQPAY (QQ 支付),JDPAY(京东支付); payType=5 时必填，支持: ALIPAY(支付宝),WECHATPAY(微 信);payType=6 时必填，支持: ALIPAY(支付宝),WECHATPAY(微 信);payType=7,8 时必填，支持: ALIPAY(支付宝),WECHATPAY(微 信);payType=9 时必填，支持: HNACARD(新生预付费卡);
            //付款方账户
            'payerAccount'      => $body['payerAccount'] ??'',//payType=3 时，必填，为发起快 捷支付的协议帐号。(通过 6.10 接口获取，或者首次支付后将返 回。)payType=5 时，必填。微信为 open_Id, 支付宝为 user_ID。
            'payCurrencyCode'       =>'CNY',//交易币种
            'settleCurrencyCode'    =>'CNY',//结算币种
            //分账标识
            'shareFlag'             => $body['shareFlag']??'0',//0:不分账 1:分账 2:延时分账
            
            
            //子订单/分账订 单信息
            'subMerchantOrderDetails'=>'',
            'returnUrl'         => $body['returnUrl'],//回调地址
            'noticeUrl'         => $body['noticeUrl'],//通知地址
            'platformId'        =>'',//平台交易时填写。由支付系统分 配给平台商户。
            'customerId'        =>'',//商户传给新生支付购买用户在 商家的用户名(需要使用快捷支 付时必填，注:使用快捷支付需 要先开通相应的产品权限)
            'customerType'      => $body['customerType']??'',//商户端下单时付款人的类型 1- 个人，2-企业。当tradeType是 0004 至 0016 间任一个必填。
            'customerName'      => $body['customerName']??'',//商户端下单时付款人名称，当 tradeType 是 0004 至 0016 间任 一个必填。
            'customerIdNo'      => $body['customerIdNo']??'',//customerType=1，个人对应身 份证号码。customerType=2 企 业对应组织机构号码。当 tradeType 是 0004 至 0016 间任 一个必填。
            'customerTel'       => $body['customerTel']??'',//当 tradeType 是 0004 至 0016 间 任一个必填。
            'bankCardNo'        => '',//商户用户银行卡 payType=3:QUICK_PAY 时必填
            'bankCardType'      => '',//商户用户银行卡 类型,当 payType=3，且卡 bin 无法识 别时必填。1:借记卡2:贷记卡
            'expireData'        => '',//有效期,BankCardType=2 时必填，格式: MMYY，如:0312
            'cvn'               => '',//BankCardType=2 时必填,如: 888
            'remark'            => '',
            'reserve1'          =>'',
            'reserve2'          => $body['reserve2']??'',//当微信备案>1 时必填。该字段 为 APPID。
            'terminalInfo'      => $body['terminalInfo']??''
        ];
        $request = [
            'head'      => $head,
            'content'   => $content
        ];
        return $this->execute('pay_order',$request);
    }

    /**
     * 查询支付结果情况
     * @param array $body
     * @return int[]|string[]|array[]
     */
    public function queryPay(array $body)
    {
        $head=[
            'serCode'   =>'101007',//服务代码
            'merCode'   => $this->config['merCode'],//商户代码
            'orderId'   => (string)time().rand(100,999),//请求流水号交易唯一标识
            'merDate'   => date('Ymd'),//商户订单日期
            'merTime'   => date('His'),//商户订单时间
            'versionNo' => '2.0',
            'signType'  => '2'
        ];
        $request = [
            'head'      => $head,
            'content'   => $body
        ];
        return $this->execute('pay_query',$request);
    }
    
    /**
     * 支付单报关
     */
    public function reportPay(array $body){
        $head=[
            'serCode'=>'101017',//服务代码
            'merCode'=> $this->config['merCode'],//商户代码
            'orderId'=>(string)time().rand(100,99999),//请求流水号交易唯一标识
            'merDate'=>date('Ymd'),//商户订单日期
            'merTime'=>date('His'),//商户订单时间
            'versionNo'=>'2.0',
            'signType'=>'2'
        ];
        $request = [
            'head'      => $head,
            'content'   => $body
        ];
        return $this->execute('pay_reportpay',$request);
    }
    
    /**
     * 退款
     * @param array $body
     * @return type
     */
    public function returnOrder(array $body)
    {
        $head=[
            'serCode'=>'101006',//服务代码
            'merCode'=> $this->config['merCode'],//商户代码
            'orderId'=>(string)time().rand(100,999),//请求流水号交易唯一标识
            'merDate'=>date('Ymd'),//商户订单日期
            'merTime'=>date('His'),//商户订单时间
            'versionNo'=>'2.0',
            'signType'=>'2'
        ];
        $request = [
            'head'      => $head,
            'content'   => $body
        ];
        return $this->execute('pay_return_order',$request);
    }
    
    /**
     * 签名
     */
    public function makeSign( array $array = [] )
    {
        $headcont= json_encode($array,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
        $merchantPubKey=$this->config['merchantPubKey'];
        $signMsg= md5(md5($headcont).$merchantPubKey);
        return $signMsg;
    }
    
    /**
     * 推送接口
     * @param string $method
     * @param array $body
     */
    public function execute(string $method, array $data)
    {
        $data['sign'] = $this->makeSign($data);
        $pushData = [
            'msg'   => base64_encode(json_encode($data,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES))
        ];
        $parameter = [
            [
                'tag'       => 'hnapay_'.$method,
                'url'       => $this->url,
                'data'      => $pushData,
                'method'    => 'post',
                'format'    => 'x-www-form-urlencoded',
                'header'    => [
                ],
            ],
        ];
        $resTask    = TaskWorker::instance()->addTask($parameter);
        $resTask    = current($resTask);
        $response   = @json_decode($resTask['response']['result'],true);
        
        if( isset($response['msg']) ) {
            $response_json = base64_decode($response['msg']);
            $response_data = json_decode($response_json,true);
            if( isset($response_data['content']) && isset($response_data['content']['responseCode']) )
            {
                if( in_array($response_data['content']['responseCode'],['0000','0001']) ) {
                    return Normal::returnCode(Normal::SUC,"请求成功",$response_data);
                }
                
                $responseDesc = $response_data['content']['responseDesc'] ?? '请求处理失败[10000]';
                return Normal::returnCode(Normal::FAIL,$responseDesc,$response_data);
            }
        }
        
        $errMsg = $response['errMsg'] ?? '请求处理失败[10001]';
        return Normal::returnCode(Normal::FAIL,$errMsg,$response);
    }
}
